package com.fjwt.gz.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fjwt.gz.components.mq.constant.WebSocketConstants;
import com.fjwt.gz.components.mq.websocket.server.PCWsChannelServer;
import com.fjwt.gz.components.oss.model.OssFileConfig;
import com.fjwt.gz.core.constants.Constants;
import com.fjwt.gz.core.exception.BizException;
import com.fjwt.gz.core.model.ApiRes;
import com.fjwt.gz.core.model.security.GzUserDetails;
import com.fjwt.gz.db.dto.AwardMchDTO;
import com.fjwt.gz.db.dto.MchDestroyDTO;
import com.fjwt.gz.db.entity.*;
import com.fjwt.gz.db.vo.AwardMchVO;
import com.fjwt.gz.service.mapper.AwardCouponMapper;
import com.fjwt.gz.service.mapper.AwardMchMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 奖品可核销商户对应关系表/商户活动渠道表 服务实现类
 * </p>
 *
 * @author shiyonghao
 * @since 2025-04-09
 */
@Slf4j
@Service
public class AwardMchService extends ServiceImpl<AwardMchMapper, AwardMchEntity> {


    @Resource
    private AwardMchMapper awardMchMapper;

    @Autowired
    private MchInfoService mchInfoService;

    @Autowired
    private OssRecordService ossRecordService;

    @Autowired
    private ActivityAwardService activityAwardService;

    @Autowired
    private AwardCouponService awardCouponService;

    @Autowired
    private AwardGoodsService awardGoodsService;

    @Autowired
    private AwardScoreService awardScoreService;

    @Autowired
    private AwardVirtualService awardVirtualService;
    @Autowired
    private AwardCouponMapper awardCouponMapper;
    @Autowired
    private PCWsChannelServer pcWsChannelServer;

    /**
     * 获取卡券可核销商户列表
     */
    public IPage<AwardMchVO> getMchDestroyList(IPage iPage, AwardMchDTO awardMchDTO) {
        if (awardMchDTO.getAwardId() == null || awardMchDTO.getAwardType() == null) {
            throw new BizException("请求参数缺失！");
        }
        if(awardMchDTO.getAwardType().equals(Constants.AWARD.COUPON)){
          String ifCode =  awardCouponMapper.selectIfCode(awardMchDTO.getAwardId());
            IPage<AwardMchEntity> page = awardMchMapper.getMchDestroyList(iPage, awardMchDTO);
            IPage<AwardMchVO> pageVo = page.convert(e -> {
                AwardMchVO awardMchVO = BeanUtil.copyProperties(e, AwardMchVO.class);
                // 判断卡券出资方
                if (StringUtils.isNotEmpty(ifCode) && "hkpay".equals(ifCode)) {
                    //在判断是否为hk已配置商户
                    if (StringUtils.isEmpty(awardMchVO.getWechatSubmerchantNo())) {
                        awardMchVO.setBelongToHkMch(0);
                    }else {
                        awardMchVO.setBelongToHkMch(1);
                    }
                }
                return awardMchVO;
            });
            return pageVo;
        }
        IPage<AwardMchEntity> page = awardMchMapper.getMchDestroyList(iPage, awardMchDTO);
        IPage<AwardMchVO> pageVo = page.convert(e -> {
            AwardMchVO awardMchVO = BeanUtil.copyProperties(e, AwardMchVO.class);
            return awardMchVO;
        });
        return pageVo;
    }

    /**
     * 获取可核销卡券的商户
     *
     * @param couponId
     * @return
     */
    public List<AwardMchEntity> queryMchInfoByCouponId(Long couponId, Integer awardType) {
        AwardMchDTO awardMchDTO = new AwardMchDTO();
        awardMchDTO.setAwardId(couponId);
        awardMchDTO.setAwardType(awardType);
        return awardMchMapper.getMchDestroyList(awardMchDTO);
    }

    /**
     * 卡券添加单个可核销商户
     *
     * @param awardMchDTO
     */
    public void addOneMchDestroy(AwardMchDTO awardMchDTO) {
        if (ObjectUtils.isEmpty(awardMchDTO.getAwardId()) || StrUtil.isBlank(awardMchDTO.getMchNo())
                || awardMchDTO.getAwardType() == null || awardMchDTO.getIsChannelDisplay() == null) {
            throw new BizException("参数异常，请检查！");
        }
        // 查询该商户是否已添加
        AwardMchEntity awardMchEntity = awardMchMapper.selectOne(AwardMchEntity.gw()
                .eq(AwardMchEntity::getAwardId, awardMchDTO.getAwardId())
                .eq(AwardMchEntity::getMchNo, awardMchDTO.getMchNo())
                .eq(AwardMchEntity::getAwardType, awardMchDTO.getAwardType()));
        if (ObjectUtils.isNotEmpty(awardMchEntity)) {
            throw new BizException("该商户已添加");
        }
        // 查询该商户是否存在
        MchInfoEntity mchInfo = mchInfoService.getById(awardMchDTO.getMchNo());
        if (ObjectUtils.isEmpty(mchInfo)) {
            throw new BizException("该商户不存在");
        }
        // 新增
        AwardMchEntity awardMchDto = new AwardMchEntity();
        awardMchDto.setAwardId(awardMchDTO.getAwardId());
        awardMchDto.setMchNo(awardMchDTO.getMchNo());
        awardMchDto.setAwardType(awardMchDTO.getAwardType());
        awardMchDto.setIsChannelDisplay(awardMchDTO.getIsChannelDisplay());
        awardMchDto.setNumVerify(0);

        awardMchMapper.insert(awardMchDto);
    }

    /**
     * 批量 导入可核销商户
     *
     * @param awardMchDTO
     * @return
     */
    public JSONObject importBatchMchDestroyByFile(AwardMchDTO awardMchDTO) {
        if(null == awardMchDTO.getAwardId()  || StrUtil.isBlank(awardMchDTO.getUrl())
                || awardMchDTO.getAwardType() == null){
            throw new BizException("请求参数异常!");
        }
        //获取导入的商户数据
        List<MchDestroyDTO> list = this.getMchDestroyToList(awardMchDTO.getUrl());
        if (CollUtil.isEmpty(list)) {
            throw new BizException("未读取到可核销商户文件内容!");
        }
        List<String> mchNos = list.stream().map(MchDestroyDTO::getMchNo).collect(Collectors.toList());

        // 根据导入的商户号集查询商户
        List<MchInfoEntity> existingMchInfos = mchInfoService.listByIds(mchNos);
        if (CollUtil.isEmpty(existingMchInfos)) {
            throw new BizException("未找到可核销商户！请核实商户号！");
        }
        Long awardId = awardMchDTO.getAwardId();
        Integer awardType = awardMchDTO.getAwardType();

        //存在的可核销商户集
        Set<String> existingMchNos = existingMchInfos.stream()
                .map(MchInfoEntity::getMchNo)
                .collect(Collectors.toSet());

        // 查询奖品对应已保存的可核销商户记录
        List<AwardMchEntity> existingAwardMch = awardMchMapper.selectList(AwardMchEntity.gw()
                .eq(AwardMchEntity::getAwardId, awardId)
                .eq(AwardMchEntity::getAwardType, awardType)
                .in(AwardMchEntity::getMchNo, mchNos));
        Set<String> existingAwardMchNos = new HashSet<>();
        if (!CollUtil.isEmpty(existingAwardMch)) {
            existingAwardMchNos = existingAwardMch.stream()
                    .map(AwardMchEntity::getMchNo)
                    .collect(Collectors.toSet());
        }

        //导入失败的商户号
        List<String> errList = new ArrayList<>();
        //导入成功的商户号
        List<String> successList = new ArrayList<>();
        List<MchDestroyDTO> successMchList = new ArrayList<>();

        for (int i = 0; i < list.size(); i++) {
            MchDestroyDTO mchDestroyDTO = list.get(i);
            String mchNo = mchDestroyDTO.getMchNo();

            if (!existingMchNos.contains(mchNo)) {
                //商户信息不存在，无法导入
                errList.add(mchNo);
//                pcWsChannelServer.convertAndSend(String.valueOf(GzUserDetails.getCurrentUserDetails().getSysUserId()), list.size(), "导入文档", "第" + (i + 1) + "行，商户信息不存在！", WebSocketConstants.ImportStatus.FAIL);
                continue;
            }

            if (!CollUtil.isEmpty(existingAwardMch) && existingAwardMchNos.contains(mchNo)) {
                //该奖品已经添加过的商户，不导入
                errList.add(mchNo);
//                pcWsChannelServer.convertAndSend(String.valueOf(GzUserDetails.getCurrentUserDetails().getSysUserId()), list.size(), "导入文档", "第" + (i + 1) + "行，该奖品已经添加过的商户！", WebSocketConstants.ImportStatus.FAIL);
                continue;
            }
            successList.add(mchNo);
            String isChannelDisplayVal = mchDestroyDTO.getIsChannelDisplayVal();
            mchDestroyDTO.setIsChannelDisplay("是".equals(isChannelDisplayVal) ? 1 : 0);
            successMchList.add(mchDestroyDTO);
//            pcWsChannelServer.convertAndSend(String.valueOf(GzUserDetails.getCurrentUserDetails().getSysUserId()), list.size(), "导入文档", "第" + (i + 1) + "行，新增成功！", WebSocketConstants.ImportStatus.SUCCESS);
        }

        if (successMchList.isEmpty()) {
            throw new BizException("没有可新增的商户号，请核实该批商户号是否已添加！");
        }
        JSONObject result = new JSONObject();
        result.put("successList", successList);
        result.put("errList", errList);
        int i = this.saveMchList(awardId, successMchList, awardType);
        if (i <= 0 ){
            throw new BizException("导入失败！");
        }
        return result;
//        try {
//            if (CollUtil.isNotEmpty(successMchList)) {
//                this.saveMchList(awardId, successMchList, awardType);
//            }
//        } catch (Exception e) {
//            throw new BizException("导入失败");
//        }
    }

    /**
     * 添加卡券核销商户
     *
     * @param couponId  卡券ID
     * @param mchArray  商户号集合
     * @param awardType
     * @return
     */
    public int saveMchList(Long couponId, List<MchDestroyDTO> mchArray, Integer awardType) {
        return awardMchMapper.saveMchList(couponId, mchArray, awardType);
    }

    /**
     * 通过导入的oss文件获取可核销商户列表
     *
     * @return
     */
    public List<MchDestroyDTO> getMchDestroyToList(String ossFileUrl) {
        File file = FileUtil.file(String.format("./temp/%s.xlsx", DateUtil.date().getTime()));
        HttpUtil.downloadFile(ossFileUrl, file);

        // 添加oos上传记录
        OssRecordEntity ossRecordEntity = new OssRecordEntity();
        //TODO:上传文件类型修改
        ossRecordEntity.setBizType(OssFileConfig.BIZ_TYPE.UPLOAD);
        ossRecordEntity.setOssUrl(ossFileUrl);
        ossRecordEntity.setFileSize(file.length());
        ossRecordEntity.setUploadType(Constants.OSS_UPLOAD_TYPE.COUPON_MCH_TYPE);
        ossRecordEntity.setSysUserId(GzUserDetails.getCurrentUserDetails().getSysUser().getSysUserId());
        ossRecordEntity.setCreatedAt(new Date());
        ossRecordService.save(ossRecordEntity);

        // 读取文件内容
        ExcelReader reader = ExcelUtil.getReader(file);
        reader.addHeaderAlias("商户号", "mchNo");
        reader.addHeaderAlias("渠道码是否可见", "isChannelDisplayVal");
        List<MchDestroyDTO> resultList = reader.readAll(MchDestroyDTO.class);
        reader.close();
        FileUtil.del(file);
        return resultList;
    }

    /**
     * 通过奖品id删除所有可核销商户数据
     *
     * @param awardId   奖品id
     * @param awardType
     */
    public void removeAllMchDestroyByAwardId(Long awardId, Integer awardType) {
        if (awardId == null || awardType == null) {
            throw new BizException("请求参数异常，请检查！");
        }
        List<ActivityAwardEntity> list = activityAwardService.list(ActivityAwardEntity.gw()
                .eq(ActivityAwardEntity::getAwardId, awardId)
                .eq(ActivityAwardEntity::getAwardType, awardType));
        if (!list.isEmpty()) {
            throw new BizException("该奖品已配置活动，不能删除！");
        }

        Integer awardState;
        switch (awardType) {
            case Constants.AWARD.COUPON:
                AwardCouponEntity couponEntity = awardCouponService.getById(awardId);
                if (couponEntity == null) {
                    throw new BizException("所对应奖品不存在，无法删除！");
                }
                awardState = couponEntity.getState();
                break;
            case Constants.AWARD.GOODS:
                AwardGoodsEntity goodsEntity = awardGoodsService.getById(awardId);
                if (goodsEntity == null) {
                    throw new BizException("所对应奖品不存在，无法删除！");
                }
                awardState = goodsEntity.getState();
                break;
            case Constants.AWARD.SCORE:
                AwardScoreEntity scoreEntity = awardScoreService.getById(awardId);
                if (scoreEntity == null) {
                    throw new BizException("所对应奖品不存在，无法删除！");
                }
                awardState = scoreEntity.getState();
                break;
            case Constants.AWARD.VIRTUAL_COUPON:
                AwardVirtualEntity virtualEntity = awardVirtualService.getById(awardId);
                if (virtualEntity == null) {
                    throw new BizException("所对应奖品不存在，无法删除！");
                }
                awardState = virtualEntity.getState();
                break;
            default:
                throw new BizException("无效的奖品类型，无法删除！");
        }
        if (awardState == Constants.AWARD_STATE.ONLINE) {
            throw new BizException("该奖品为上线状态，不能删除！");
        }

        LambdaQueryWrapper<AwardMchEntity> removeWrapper = AwardMchEntity.gw();
        removeWrapper.eq(AwardMchEntity::getAwardId, awardId);
        removeWrapper.eq(AwardMchEntity::getAwardType, awardType);
        remove(removeWrapper);
    }

    /**
     * 修改可核销商户渠道码是否可见
     * @param awardMchDTO
     */
    public void updateMchDestroyChannelDisplay(AwardMchDTO awardMchDTO) {
        if (awardMchDTO.getAwardMchId() == null || awardMchDTO.getIsChannelDisplay() == null) {
            throw new BizException("请求参数异常！");
        }
        AwardMchEntity awardMchEntity = getById(awardMchDTO.getAwardMchId());
        if (awardMchEntity == null) {
            throw new BizException("该记录不存在！");
        }
        awardMchEntity.setIsChannelDisplay(awardMchDTO.getIsChannelDisplay());
        updateById(awardMchEntity);
    }
}
